package com.xcity.game.achievement;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;

import com.alibaba.fastjson.JSON;
import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.game.ISystem;
import com.xcity.game.achievement.Achievement.State;
import com.xcity.game.battle.pve.PVEStage;
import com.xcity.game.buildv2.BuildV2;
import com.xcity.game.common.Cause;
import com.xcity.game.common.LogCause;
import com.xcity.game.common.MessageConst;
import com.xcity.game.event.GameEvents;
import com.xcity.game.item.ItemInfo;
import com.xcity.game.item.ItemTemplate;
import com.xcity.game.recharge.RechargeTemplate;
import com.xcity.pomelo.push.msg.TipPush;

import naga.x.App;
import naga.x.event.Event;

public class AchievementManager {
	
	private Player owner;
	private List<Achievement> achievements;
	
	protected static final Logger LOG = AchievementService.LOG;

	public AchievementManager(Player player, List<Achievement> achievements) {
		this.owner = player;
		if (achievements == null) {
			achievements = new ArrayList<Achievement>();
		}
		this.achievements = achievements;
		List<AchievementTemplate> list = App.getApp().getServiceManager().get(AchievementService.class).getInitAchievements();
		for (AchievementTemplate temp : list) {
			AchievementGroup group = temp.getGroup();
			if (group != AchievementGroup.UNKNOWN
					&& group.isAvailable()
					&& findByGroup(group) == null) {
				achievements.add(new Achievement(this, temp));
			}
		}
		for (int i = 0; i < achievements.size(); i++) {
			achievements.get(i).vm = this;
		}
	}
	
	public List<Achievement> getAchievements() {
		return achievements;
	}
	
	/**
	 * 根据成就类型查找
	 * @param group
	 * @return
	 */
	public Achievement find(AchievementGroup group) {
		for (int i = achievements.size() - 1; i >= 0; i--) {
			Achievement achievement = achievements.get(i);
			if (achievement.getTemplate().getGroup() == group) {
				return achievement;
			}
		}
		return null;
	}
	
	public Achievement findByGroup(AchievementGroup group) {
		for (int i = achievements.size() - 1; i >= 0; i--) {
			Achievement achievement = achievements.get(i);
			if (achievement.getTemplate().getGroup() == group) {
				return achievement;
			}
		}
		return null;
	}
	
	@Override
	public String toString() {
		return JSON.toJSONString(achievements);
	}

	public Achievement reward(AchievementGroup group) throws AchievementException {
		Achievement achievement;
		if (group == AchievementGroup.UNKNOWN || (achievement = find(group)) == null) {
			throw new AchievementException(MessageConst.ACHIEVE_NOT_FOUND);
		}
		if (achievement.getState() == State.INITED) {
			throw new AchievementException(MessageConst.ACHIEVE_NOT_FINISH);
		}
		if (achievement.getState() == State.REWARDED) {
			throw new AchievementException(MessageConst.ACHIEVE_REWARD_GOTTEN);
		}
		AchievementTemplate temp = achievement.getTemplate();
		if (temp == null) {
			throw new AchievementException(MessageConst.SYSTEM_ERROR);
		}
		achievement.setState(State.REWARDED);
		StringBuilder tip = new StringBuilder();
		if (temp.getGold() > 0) {
			owner.addGold(temp.getGold(), Cause.ACHIEVEMENT_REWARD);
			tip.append("现金 +").append(temp.getGold()).append("  ");
		}
		if (temp.getStone() > 0) {
			owner.addStone(temp.getStone(), Cause.ACHIEVEMENT_REWARD);
			tip.append("钻石 +").append(temp.getStone()).append("  ");
		}
		if (temp.getExp() > 0) {
			owner.addExp(temp.getExp(), Cause.ACHIEVEMENT_REWARD);
			tip.append("经验 +").append(temp.getExp()).append("  ");
		}
		if (temp.getRewardItems() != null) {
			for (ItemInfo item : temp.getRewardItems()) {
				owner.getBag().addItemWithoutException(item.getId(), item.getCount(), Cause.ACHIEVEMENT_REWARD);
				tip.append(item.getTemplate().getName()).append(" +").append(item.getCount()).append("  ");
			}
		}
		owner.send(new TipPush(tip.toString()));
		LOG.info("[ACHIEVEREWARD]ID[{}]ACHIEVEID[{}]GROUP[{}]GOLD[{}]STONE[{}]EXP[{}]", owner.getId(), achievement.getId(), temp.getGroup(), temp.getGold(), temp.getStone(), temp.getExp());
		achievement.refresh(owner);
		return achievement;
	}
	
	public void handleEvent(Event event) {
		switch (event.getType()) {
			case GameEvents.EVENT_GOLD_CHANGED:
				long val = event.getParameter(1);
				Object cause = event.getParameter(2);
				if (!Cause.BUY_FINANCIAL.equals(cause) && !Cause.BUY_LAND.equals(cause)) {
					// 过滤理财、地标消耗
					fireGoldChanged(cause, val);
				}
				break;
			case GameEvents.EVENT_PLAYER_LOGIN:
				playerLogin();
				break;
			case GameEvents.EVENT_RANKING_UPPED:
				fireRankingListEntered(event.getParameter(1));
				break;
			case GameEvents.EVENT_TAKE_MONEY_IN_BUILD:
				takeMoneyInBuilding(event.getParameter(2));
				takeMoneyInBuildingTimes(event.getParameter(2));
				break;
//			case GameEvents.EVENT_CREATE_BUILDING:
//				createBuilding(event.getParameter(1));
//				createBuildingNum(event.getParameter(1));
//				break;
			case GameEvents.EVENT_BUILDING_FINISH_V2:
				fireBuildingFinished(event.getParameter(1));
				break;
//			case GameEvents.EVENT_BUILDING_LEVEL_UP:
//				buildLevelUp(event.getParameter(1));
//				break;
//			case GameEvents.EVENT_BUILDING_LEVEL_UP_OK:
//				buildLevelUpOk(event.getParameter(1));
//				break;
			case GameEvents.EVENT_BUILDING_PART_LEVEL_UP_V2:
				fireBuildingPartLevelUp();
				break;
			case GameEvents.EVENT_START_BUILDING_V2:
				fireBuildingStart(event.getParameter(1));
				break;
			case GameEvents.EVENT_PLAYER_LEVEL_UP:
				firePlayerLevelUp();
				break;
//			case GameEvents.EVENT_SELL_BUILDING:
//				sellBuilding();
//				break;
//			case GameEvents.EVENT_SYSTEM_FINE:
//				systemFine();
//				break;
			case GameEvents.EVENT_USE_ITEM:
				fireUseItem(event.getParameter(1), event.getParameter(2));
				break;
			case GameEvents.EVENT_BUY_ITEM:
				fireBuyItem(event.getParameter(1));
				break;
//			case GameEvents.EVENT_TAKE_MONEY_IN_FRIEND_BUILD:
//			case GameEvents.EVENT_ROB_BUILD_MONEY:
//				robBuildMoney(event.getParameter(2));
//				break;
			case GameEvents.EVENT_RECHARGE:
				fireRecharged(event.getParameter(1), event.getParameter(2));
				break;
			case GameEvents.EVENT_USE_SYSTEM:
				useSystem(event.getParameter(1), event.getParameter(2));
				break;
			case GameEvents.EVENT_EMPLOYEE_ADDED:
				fireEmployeeAdded(event.getParameter(1));
				break;
			case GameEvents.EVENT_PVE_SUCCESS:
				firePVEEnded(event.getParameter(1), event.getParameter(4));
				break;
			case GameEvents.EVENT_ADVENTURE_STEAL:
				fireAdventureSteal();
				break;
			case GameEvents.EVENT_ADVENTURE_ATTACK:
				fireAdventureAttack();
				break;
		}
	}
	
	protected void playerLogin() {
		// 没有该成就了
//		Integer beRobbedTimes = (Integer) owner.poolRemove(PlayerPool.PROPERTY_OFFLINE_BE_ROBBED_TIMES);
//		if (beRobbedTimes != null) {
//			Achievement achieve = findByGroup(AchievementGroup.BE_ROBBED);
//			if (achieve != null) {
//				achieve.update(owner, beRobbedTimes.intValue());
//			}
//		}
		// 离线充值不用特殊处理，会直接取缓存更新
//		JSONArray offlineRecharges = (JSONArray) owner.poolRemove(PlayerPool.PROPERTY_OFFLINE_RECHARGE);
//		if (offlineRecharges != null) {
//			for (int i = 0, size = offlineRecharges.size(); i < size; i++) {
//				int[] record = offlineRecharges.getObject(i, int[].class);
//				RechargeTemplate template = App.getApp().getServiceManager().get(TemplateService.class).get(RechargeTemplate.class, record[1]);
//				fireRecharged(record[0], template);
//			}
//		}
	}
	
	protected void fireGoldChanged(Object cause, long value) {
		if (value > 0) {
			int sysId;
			if (cause == LogCause.ADVENTURE) {
				sysId = ISystem.SYS_ADVENTURE;
			} else {
				sysId = ISystem.UNKNOWN;
			}
			Achievement refer = findByGroup(AchievementGroup.GOLD_ADDED);
			if (refer != null) {
				refer.update(owner, (int) value, sysId);
			}
			refer = findByGroup(AchievementGroup.GOLD_ADDED_BY_SYS);
			if (refer != null) {
				refer.update(owner, (int) value, sysId);
			}
		} else {
			Achievement refer = findByGroup(AchievementGroup.GOLD_COST);
			if (refer != null) {
				refer.update(owner, (int) -value);
			}
		}
	}
	
	public void fireRankingListEntered(int ranking) {
		Achievement achieve = findByGroup(AchievementGroup.ENTER_RANKING_LIST);
		if (achieve != null) {
			achieve.update(owner, ranking);
		}
	}
	
	protected void takeMoneyInBuilding(int money) {
		Achievement achieve = findByGroup(AchievementGroup.TAKE_MONEY_FROM_BUILDING);
		if (achieve != null) {
			achieve.update(owner, money);
		}
	}
	
	protected void takeMoneyInBuildingTimes(int money) {
		Achievement achieve = findByGroup(AchievementGroup.TAKE_MONEY_TIMES);
		if (achieve != null) {
			achieve.update(owner, 1);
		}
	}
	
//	Achievement createBuilding(Build build) {
//		Achievement achieve = findByGroup(Group.CREATE_BUILDINGS);
//		return achieve != null && achieve.update(owner, build.getId()) ? achieve : null;
//	}
//	
//	Achievement createBuildingNum(Build build) {
//		Achievement achieve = findByGroup(Group.BUILDINGS_NUM);
//		return achieve != null && achieve.update(owner, 1) ? achieve : null;
//	}
	
	protected void fireBuildingFinished(BuildV2 building) {
		Achievement achieve = findByGroup(AchievementGroup.CREATE_BUILDINGS);
		if (achieve != null) {
			achieve.update(owner, building.getId());
		}
		achieve = findByGroup(AchievementGroup.BUILDINGS_NUM);
		if (achieve != null) {
			achieve.update(owner, null);
		}
	}
	
	protected void fireBuildingPartLevelUp() {
		Achievement achieve = findByGroup(AchievementGroup.BUILDING_LEVEL_UP_TIMES);
		if (achieve != null) {
			achieve.update(owner, 1);
		}
	}
	
	protected void fireBuildingStart(BuildV2 building) {
		Achievement achieve = findByGroup(AchievementGroup.CREATE_BUILDING_V2);
		if (achieve != null) {
			achieve.update(owner, 1);
		}
	}
	
//	Achievement buildLevelUp(Build build) {
//		Achievement achieve = findByGroup(Group.BUILDING_LEVEL_UP_TIMES);
//		return achieve != null && achieve.update(owner, 1) ? achieve : null;
//	}
	
//	Achievement buildLevelUpOk(Build build) {
//		Achievement achieve = findByGroup(Group.BUILDING_LEVEL_UP);
//		return achieve != null && achieve.update(owner, build.getLevel()) ? achieve : null;
//	}
	
//	Achievement systemFine() {
//		Achievement achieve = findByGroup(Group.SYSTEM_FINE);
//		return achieve != null && achieve.update(owner, 1) ? achieve : null;
//	}
//	
//	Achievement sellBuilding() {
//		Achievement achieve = findByGroup(Group.SELL_BUILDING);
//		return achieve != null && achieve.update(owner, 1) ? achieve : null;
//	}
	
	protected void fireUseItem(ItemTemplate item, int count) {
		fireUseItem(item.getId(), count);
	}
	
	public void fireUseItem(int itemId, int count) {
		Achievement achieve = findByGroup(AchievementGroup.USE_ITEM_OR_GET_SHIELD);
		if (achieve != null) {
			achieve.update(owner, itemId, count);
		}
	}
	
	protected void fireBuyItem(int itemId) {
		Achievement achieve = findByGroup(AchievementGroup.BUY_ITEM);
		if (achieve != null) {
			achieve.update(owner, itemId, 1);
		}
	}
	
//	void robBuildMoney(int money) {
//		Achievement achieve = findByGroup(Group.ROB_TOTAL_MONEY);
//		if (achieve != null) {
//			achieve.update(owner, money);
//		}
//	}
	
	protected void fireRecharged(int money, RechargeTemplate template) {
		Achievement achieve = findByGroup(AchievementGroup.RECHARGE_SUM);
		if (achieve != null) {
			achieve.update(owner, template != null ? template.getPrice() : money);
		}
		achieve = findByGroup(AchievementGroup.RECHARGE_SOMEONE);
		if (achieve != null) {
			achieve.update(owner, template.getId());
		}
	}
	
	protected void useSystem(int systemId, Integer num) {
		Achievement achieve = findByGroup(AchievementGroup.USE_SYSTEM_FUNCTION);
		if (achieve != null) {
			achieve.update(owner, systemId, num != null && num > 0 ? num : 1);
		}
	}
	
	protected void firePlayerLevelUp() {
		Achievement achieve = findByGroup(AchievementGroup.LEVEL_UP);
		if (achieve != null) {
			achieve.update(owner, null);
		}
	}
	
	protected void fireEmployeeAdded(Employee employee) {
		Achievement achieve = findByGroup(AchievementGroup.EMPLOYEE_SIZE);
		if (achieve != null) {
			achieve.update(owner, null);
		}
		achieve = findByGroup(AchievementGroup.EMPLOYEE_QUALITY);
		if (achieve != null) {
			achieve.update(owner, null);
		}
	}
	
	protected void firePVEEnded(PVEStage stage, boolean isFirstPass) {
		if (isFirstPass) {
			Achievement achieve = findByGroup(AchievementGroup.PASS_PVE);
			if (achieve != null) {
				achieve.update(owner, null);
			}
		}
	}
	
	protected void fireAdventureSteal() {
		Achievement achieve = findByGroup(AchievementGroup.ADVENTURE_STEAL);
		if (achieve != null) {
			achieve.update(owner, 1);
		}
	}
	
	protected void fireAdventureAttack() {
		Achievement achieve = findByGroup(AchievementGroup.ADVENTURE_ATTACK);
		if (achieve != null) {
			achieve.update(owner, 1);
		}
	}

	public void init(Player player) {
		this.owner = player;
	}
	
	public Player getOwner() {
		return owner;
	}

}
